package com.ruoyi.web.controller.system;


import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.domain.vo.ImportProgressVo;
import com.ruoyi.common.core.domain.vo.UploadFileVo;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.OrikaUtils;
import com.ruoyi.common.utils.PlaceHttpUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.system.domain.SysPlace;
import com.ruoyi.system.domain.vo.PlaceInfoTemplateResultVo;
import com.ruoyi.system.domain.vo.PlaceInfoTemplateVo;
import com.ruoyi.system.domain.vo.SelectByPlaceLevelVo;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysPlaceService;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.util.*;

import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;

/**
 * 地区管理Controller
 *
 * @author linyang
 * @date 2024-01-17
 */
@RestController
@RequestMapping("/system/place")
public class SysPlaceController extends BaseController {
    @Resource
    private ISysPlaceService sysPlaceService;

    @Resource
    private ISysConfigService configService;


    @Resource
    private RedisCache redisCache;


    /**
     * 查询地区管理列表
     */
    //@PreAuthorize("@ss.hasPermi('system:place:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysPlace sysPlace) {
        startPage();
        List<SysPlace> list = sysPlaceService.selectSysPlaceList(sysPlace);
        return getDataTable(list);
    }


    /**
     * 根据关键字查询地区列表
     *
     * @param keyword
     * @return
     */
    @GetMapping("/search/{keyword}")
    public AjaxResult search(@PathVariable("keyword") String keyword) {
        return success(sysPlaceService.selectSearchSysPlaceList(keyword));
    }


    /**
     * 导出地区管理列表
     */
    //@PreAuthorize("@ss.hasPermi('system:place:export')")
    //@Log(title = "地区管理", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysPlace sysPlace) {
        List<SysPlace> list = sysPlaceService.selectSysPlaceList(sysPlace);
        ExcelUtil<SysPlace> util = new ExcelUtil<SysPlace>(SysPlace.class);
        util.exportExcel(response, list, "地区管理数据");
    }

    /**
     * 获取地区管理详细信息
     */
    //@PreAuthorize("@ss.hasPermi('system:place:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return success(sysPlaceService.selectSysPlaceById(id));
    }

    /**
     * 新增地区管理
     */
    //@PreAuthorize("@ss.hasPermi('system:place:add')")
    @Log(title = "地区管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody SysPlace sysPlace) {
        return toAjax(sysPlaceService.insertSysPlace(sysPlace));
    }

    /**
     * 修改地区管理
     */
    //@PreAuthorize("@ss.hasPermi('system:place:edit')")
    @Log(title = "地区管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody SysPlace sysPlace) {
        return toAjax(sysPlaceService.updateSysPlace(sysPlace));
    }

    /**
     * 删除地区管理
     */
    //@PreAuthorize("@ss.hasPermi('system:place:remove')")
    @Log(title = "地区管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(sysPlaceService.deleteSysPlaceByIds(ids));
    }


    /**
     * 下载导入模板
     *
     * @param response
     * @throws Exception
     */
    @PostMapping("/downloadTemplate")
    public void downloadTemplate(HttpServletResponse response) throws Exception {
        String fileName = "place_info_template.xlsx";
        String path = configService.selectConfigByKey("sys.template.download.path");
        String filePath = path + fileName;
        File file = new File(filePath);
        if (file.exists()) {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8");
            FileUtils.setAttachmentResponseHeader(response, "place_info_template.xlsx");
            FileUtils.writeBytes(filePath, response.getOutputStream());
        }
    }

    /**
     * 上传地区信息文件
     *
     * @param file
     * @return
     * @throws Exception
     */
    @PostMapping("/upload")
    public AjaxResult uploadFile(MultipartFile file) throws IOException {
        String fileExt = FileUploadUtils.getExtension(file);//文件后缀名
        String newName = UUID.fastUUID().toString().replace("-", "");//随机生成uuid文件名
        String configPath = configService.selectConfigByKey("sys.upload.data.file.path");
        String savePath = configPath + newName + "." + fileExt;
        File newFile = new File(savePath);
        file.transferTo(newFile);
        return success(newName + "." + fileExt);
    }


    /**
     * 导入数据
     *
     * @param fileReq
     * @return
     * @throws Exception
     */
    @PostMapping("/importData")
    public AjaxResult importData(@RequestBody UploadFileVo fileReq) throws Exception {
        LoginUser loginUser = getLoginUser();
        Date now = DateUtils.getNowDate();
        //获取上传路径
        String configPath = configService.selectConfigByKey("sys.upload.data.file.path");
        File file = new File(configPath + fileReq.getFileName());
        InputStream is = new FileInputStream(file);
        List<PlaceInfoTemplateVo> recordList = EasyExcel.read(is).head(PlaceInfoTemplateVo.class).sheet().doReadSync();
        List<PlaceInfoTemplateResultVo> resultList = new ArrayList<>();
        ImportProgressVo progressVo = new ImportProgressVo();
        if (recordList != null && recordList.size() > 0) {
            progressVo.setCountNum(recordList.size());//获取数据总数
            for (PlaceInfoTemplateVo vo : recordList) {
                PlaceInfoTemplateResultVo resultVo = OrikaUtils.convert(vo, PlaceInfoTemplateResultVo.class);
                try {
                    SysPlace sysPlace = OrikaUtils.convert(vo, SysPlace.class);
                    if (vo.getIsNeedExtend().equals("需要")){
                        sysPlace.setIsNeedExtend("0");
                    }
                    else{
                        sysPlace.setIsNeedExtend("1");
                    }
                    sysPlace.setCreateBy(loginUser.getUsername());
                    sysPlace.setCreateTime(now);
                    sysPlaceService.insertSysPlace(sysPlace);
                    resultVo.setOpStatus("成功");
                    resultList.add(resultVo);
                    progressVo.addSuccessNum();
                } catch (Exception ex) {
                    //出错
                    resultVo.setOpStatus("失败");
                    resultVo.setMsg(ex.getMessage());
                    resultList.add(resultVo);
                    progressVo.addFailureNum();
                }
                progressVo.addOpNum();
                String test = this.getPercent(progressVo.getOpNum(), progressVo.getCountNum());
                redisCache.setCacheObject(fileReq.getFileName(), test);
            }
        }
        String fileExt = file.getName().substring(file.getName().lastIndexOf("."), file.getName().length());
        String newName = UUID.fastUUID().toString().replace("-", "");//随机生成uuid文件名
        String configResultPath = configService.selectConfigByKey("sys.upload.result.file.path");
        String resultFileName = configResultPath + newName + fileExt;
        EasyExcel.write(resultFileName, PlaceInfoTemplateResultVo.class).sheet("sheet1").registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).doWrite(resultList);
        progressVo.setResultFileName(newName + fileExt);
        redisCache.setCacheObject(fileReq.getFileName(), "100");
        //TODO 导入完成后，需要删除数据 或者 定时删除数据
        return success(progressVo);
    }


    /**
     * 获取当前文件的导出进度
     *
     * @param fileName
     * @return
     */
    @GetMapping("/importDataProgress/{fileName}")
    public AjaxResult importDataProgress(@PathVariable("fileName") String fileName) {
        if (StringUtils.isEmpty(fileName)) {
            return success(0);
        }
        String percent = redisCache.getCacheObject(fileName);
        if (StringUtils.isEmpty(percent)) {
            return success(0);
        }
        return success(percent);
    }


    /**
     * 导出上传结果
     *
     * @param response
     * @throws Exception
     * @RequestBody UploadFileVo fileReq,
     */
    @PostMapping("/exportUploadResult")
    public void exportUploadResult(@RequestParam(value = "fileName") String fileName, HttpServletResponse response) throws Exception {
        String path = configService.selectConfigByKey("sys.upload.result.file.path");
        String filePath = path + fileName;
        File file = new File(filePath);
        if (file.exists()) {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8");
            FileUtils.setAttachmentResponseHeader(response, fileName);
            FileUtils.writeBytes(filePath, response.getOutputStream());
        }
    }


    /**
     * 填充地区名称（阿里云云市场）
     *
     * @return
     * @throws Exception
     */
    @PostMapping("/fillFullName/{id}")
    public AjaxResult fillFullName(@PathVariable("id") Long id) throws Exception {
        SysPlace sysPlace = sysPlaceService.selectSysPlaceById(id);
        if (sysPlace.getIsNeedExtend().equals("1")) {
            return error("当前地区不需要扩展");
        }
        String host = "https://addre.market.alicloudapi.com";
        String path = "/format";
        String method = "GET";
        String appcode = "dad81628ba27428bb77d45fd709311a4";
        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", "APPCODE " + appcode);
        Map<String, String> querys = new HashMap<>();
        querys.put("text", sysPlace.getName());
        HttpResponse response = PlaceHttpUtils.doGet(host, path, method, headers, querys);
        //System.out.println(EntityUtils.toString(response.getEntity()));
        //返回格式，response只能读一次
        //{"msg":"ok","code":1,"data":{"town_code":"","address":"河北省石家庄市长安区","province":"河北省","town":"","city":"石家庄市","county_code":"130102","person":"","county":"长安区","city_code":"130100","detail":"","phonenum":"","province_code":"130000"},"text":"河北省石家庄市长安区"}
        JSONObject jsonObject = JSONObject.parseObject(EntityUtils.toString(response.getEntity()));
        if (ObjectUtil.isEmpty(jsonObject)) {
            return error("解析地址失败，请和管理员联系");
        }
        Object data = jsonObject.get("data");
        jsonObject = JSONObject.parseObject(JSONObject.toJSONString(data));
        sysPlace.setFullName(jsonObject.get("address").toString());
        sysPlace.setProvince(jsonObject.get("province").toString());
        if (jsonObject.get("province").equals(jsonObject.get("city"))) {
            sysPlace.setCity(jsonObject.get("county").toString());
            sysPlace.setCounty("");
        } else {
            sysPlace.setCity(jsonObject.get("city").toString());
            sysPlace.setCounty(jsonObject.get("county").toString());
        }
        sysPlaceService.updateSysPlace(sysPlace);
        return success("操作成功！");
    }


    /**
     * 根据地区级别查询地区列表
     *
     * @param vo
     * @return
     */
    @GetMapping("/selectByPlaceLevel")
    public AjaxResult selectByPlaceLevel(SelectByPlaceLevelVo vo) {
        return success(sysPlaceService.selectByPlaceLevel(vo));
    }


    /**
     * 计算百分比
     * 不包含百分号
     * 非控制器
     *
     * @param x
     * @param y
     * @return
     */
    private String getPercent(Integer x, Integer y) {
        double f = x * 100 / y;
        NumberFormat nf = NumberFormat.getNumberInstance();
        nf.setRoundingMode(RoundingMode.HALF_UP);
        nf.setGroupingUsed(true);
        return nf.format(f);
    }
}
